#include "DmaBufManager.h"

namespace camera
{
    namespace algorithm
    {
        DmaBufManager::DmaBufManager()
        {
            mWmarkDev = WmarkDev::getInstance();
            mWmarkDev->registerCtlMsgCallback(this);
            mInitFlag = false;
        }

        DmaBufManager::~DmaBufManager()
        {
            if (mWmarkDev) {
                mWmarkDev->registerCtlMsgCallback(NULL);
            }
        }

        int DmaBufManager::initDmaBuf()
        {
            init_dma_bufs_t msg;
            int ret = -1;
            int count = -1;

            mMutex.lock();

            if (mInitFlag) {
                ret = 0;
                goto free_lock;
            }

            // 获得 DmaBuf 信息
            ALOGD("cmd=%lu msg=%p", (unsigned long)GET_INIT_DMA_BUFS, &msg);
            ret = mWmarkDev->ioctlDev(GET_INIT_DMA_BUFS, (void *)&msg);
            if (ret)
            {
                ALOGE("%s %d get dma buf info error\n", __func__, __LINE__);

                goto free_lock;
            }

            count = msg.dma_buf_num;
            for (size_t i = 0; i < count; i++)
            {
                int index = msg.dma_fds[i].index;
                if (index < 0 || index >= DMA_BUFS_MAX_NUM)
                {
                    ALOGE("%s %d get dma buf index=%d error\n", __func__, __LINE__, index);
                    ret = -1;
                    goto free_lock;
                }

                mIonBufsInfo[index].buffd = msg.dma_fds[i].fd;
                mIonBufsInfo[index].buflen = msg.dma_fds[i].buf_len;
                ALOGD("get index[%d] client fd=%d buf_len=%ld buffer=%p\n", index, mIonBufsInfo[index].buffd, mIonBufsInfo[index].buflen, mIonBufsInfo[index].buffer);
            }

            // 根据 DmaBuf 信息， 建立 DmaBuf 映射
            ion_import_buffer_fds(mIonBufsInfo);

            printf_ion_buffer_info(mIonBufsInfo);

            for (size_t i = 0; i < DMA_BUFS_MAX_NUM; i++)
            {
                mWmarkDev->setFreeWBufInfo(i);
            }

            ret = 0;
            mInitFlag = true;

        free_lock:
            mMutex.unlock();
            return ret;
        }

        struct ion_buffer_info *DmaBufManager::indexToBufAddr(int index)
        {
            struct ion_buffer_info *retAddr = NULL;

            mMutex.lock();
            if (!mInitFlag) {
                retAddr = NULL;
                ALOGV("%s %d mInitFlag = false\n", __func__, __LINE__);
                goto free_lock;
            }

            if (index < 0 || index >= DMA_BUFS_MAX_NUM)
            {
                ALOGE("%s %d index=%d error\n", __func__, __LINE__, index);
                retAddr = NULL;
                goto free_lock;
            }


            retAddr = &mIonBufsInfo[index];
            

            printf_ion_buffer_info(mIonBufsInfo);

            ALOGW("mIonBufsInfo[%d].buffer = %p", index, retAddr->buffer);
            // checkData(retAddr->buffer, retAddr->buflen);
        
        free_lock:
            mMutex.unlock();
            return retAddr;
        }

        void DmaBufManager::checkData(uint8_t *buffer, uint64_t len)
        {
            int i;
            unsigned char *ptr = (unsigned char *)buffer;
            int count = 0;

            if (!ptr)
            {
                fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
                return;
            }

            for (i = 0; i < len; i++)
            {
                if (ptr[i] != 0)
                {
                    count++;
                }
            }

            ALOGD("%s %d : len = %lu !=0 cout=%d", __func__, __LINE__, (unsigned long)len, count);

            printf("\n");
        }

        // 用于处理 control msg 信息
        void DmaBufManager::onResult(control_msg_t &info)
        {
            switch (info.state)
            {
            case S_M_OPEN_EX:
                ALOGD("%s %d : S_M_OPEN_EX\n", __func__, __LINE__);
                break;
            case S_M_INIT_OK_EX:
                initDmaBuf();
                ALOGD("%s %d : S_M_INIT_OK_EX\n", __func__, __LINE__);
                break;
            case S_M_INIT_ERROR_EX:
                ALOGD("%s %d : S_M_INIT_ERROR_EX\n", __func__, __LINE__);
                break;
            case S_M_CLOSE_EX:
                ALOGD("%s %d : S_M_CLOSE_EX\n", __func__, __LINE__);
                uninitDmaBuf();
                break;

            default:
                ALOGE("%s %d : state fail\n", __func__, __LINE__);
                break;
            }
            return;
        }

        int DmaBufManager::uninitDmaBuf()
        {
            int ret = -1;

            mMutex.lock();

            if (!mInitFlag) {
                ret = 0;
                goto free_lock;
            }

            ion_close_buffers_fd(mIonBufsInfo);
            mInitFlag = false;

        free_lock:
            mMutex.unlock();
            return ret;
        }

    } // algorithm
} // camera